home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 6 / a86v319c.zip / A12.DOC < prev    next >
Text File  |  1988-05-20  |  14KB  |  301 lines

  1. CHAPTER 12   COMPATIBILITY WITH OTHER ASSEMBLERS
  2.  
  3.  
  4. I gave heavy priority to compatibility when I designed A86; a
  5. priority just a shade behind the higher priorities of
  6. reliability, speed, convenience, and power.  For those of you who
  7. feel that "close, but incompatible" is like saying "a little bit
  8. pregnant", I'm sorry to report that A86 will not assemble all
  9. Intel/IBM/MASM programs, unmodified. But I do think that a vast
  10. majority of programs can, with surprisingly little massaging, be
  11. made to assemble under A86.  Furthermore, the massaging can be
  12. done in such a way as to make the programs still acceptable to
  13. that old, behemoth assembler.
  14.  
  15. Version 3.00 of A86 has many compatibility features not present
  16. in earlier versions.  Among the features added since A86 was
  17. first released are:  more general forward references, double
  18. quotes for strings, "=" as a synonym for EQU, the RADIX
  19. directive, and the COMMENT directive.  If you tried feeding an
  20. old source file to a previous A86 and were dismayed by the number
  21. of error messages you got, try again: things might be more
  22. manageable now.
  23.  
  24.  
  25. Conversion of MASM programs to A86
  26.  
  27. Following is a list of the things you should watch out for when
  28. converting from MASM to A86:
  29.  
  30. 1. You need to determine whether the program was coded as a COM
  31.    program or as an EXE program.  All COM programs coded for MASM
  32.    will contain an ORG 100H directive somewhere before the start
  33.    of the code.  EXE programs will contain no such ORG, and will
  34.    often contain statements that load named segments into
  35.    registers.  If the program was coded as EXE, you must either
  36.    assemble it (using the +O option) to an OBJ file to be fed to
  37.    LINK, or you must eliminate the instructions that load segment
  38.    registers-- in a COM program they often aren't necessary
  39.    anyway, since COM programs are started with all segment
  40.    registers already pointing to the same value.
  41.  
  42.    A good general rule is: when it doubt, try assembling to an
  43.    OBJ file.
  44.  
  45. 2. You need to determine whether the program is executing with
  46.    all segment registers pointing to the same value.  Simple COM
  47.    programs that fit into 64K will typically fall into this
  48.    category.  Most EXE programs, programs that use huge amounts
  49.    of memory, and programs (such as memory-resident programs)
  50.    that take over interrupts typically have different values in
  51.    segment registers.
  52.                                                              12-2
  53.  
  54.    If there are different values in the segment registers, then
  55.    there may be instructions in the program for which the old
  56.    assembler generates segment override prefixes "behind your
  57.    back".  You will need to find such references, and generate
  58.    explicit overrides for them.  If there are data tables within
  59.    the program itself, a CS-override is needed.    If there are
  60.    data structures in the stack segment not accessed via a BP-
  61.    index, an SS-override is needed. If ES points to its own
  62.    segment, then an ES-override is needed for accesses (other
  63.    than STOS and MOVS destinations) to that segment.  In the
  64.    interrupt handlers to memory-resident programs, the "normal"
  65.    handler is often invoked via an indirect CALL or JMP
  66.    instruction that fetches the doubleword address of the normal
  67.    handler from memory, where it was stored by the initialization
  68.    code.  That CALL or JMP often requires a CS-override-- watch
  69.    out!
  70.  
  71.    If you want to remain compatible with the old assembler, then
  72.    code the overrides by placing the segment register name, with
  73.    a colon, before the memory-access operand in the instruction.
  74.    If you do not need further compatibility, you can place the
  75.    segment register name before the instruction mnemonic.  For
  76.    example:
  77.  
  78.     MOV AL,CS:TABLE[SI]   ; if you want compatibility do this
  79.     CS MOV AL,TABLE[SI]   ; if not you can do it this way
  80.  
  81. 2. A86 is a bit more restrictive with respect to forward
  82.    references than MASM, but not as much as it used to be. You'll
  83.    probably need to resolve just a few ambiguous references by
  84.    appending " B" or " W" to the forward reference name.  One
  85.    common reference that needs a bit more recoding is the
  86.    difference of two forward references, often used to refer to
  87.    the size of a block of allocated memory.  You handle this by
  88.    defining a new symbol representing the size, using an EQU
  89.    right after the block is declared, and then replacing the
  90.    forward-reference difference with the size symbol.
  91.  
  92. 3. A86 has the feature, not seen in MASM, that the default base
  93.    for numbers with leading digit 0 is hexadecimal, not decimal.
  94.    This means that you must remove any leading zeroes from
  95.    decimal numbers in your old programs.  Note that all constants
  96.    other than those without leading zeroes and without trailing
  97.    base-specifiers are handled identically by A86 and by MASM.
  98.    The ONLY thing you need to worry about is decimal numbers with
  99.    leading zeroes.  Example: the old code line MOV AX,00100,
  100.    meaning decimal 100, should be recoded MOV AX,100, without the
  101.    leading zeroes.
  102.  
  103.    Alternatively, I have added the RADIX command, for
  104.    compatibility with the .RADIX command of IBM's assembler.  If
  105.    the program has a .RADIX command at the top of it, then my
  106.    assembler will handle constants identically to the IBM
  107.    assembler; if it does not, you can add a .RADIX 10 to the top
  108.    of the program, for complete compatibility.
  109.                                                              12-3
  110.  
  111.    For even greater convenience, I have added the +D switch,
  112.    which you can put into your A86 environment variable, to
  113.    achieve decimal functionality without a RADIX 10 command.
  114.  
  115. 4. A86's macro definition and conditional assembly language is
  116.    different than MASM's. Most macros can be translated by
  117.    replacing the named parameters of the old macros with the
  118.    dedicated names #n of the A86 macro language; and by replacing
  119.    ENDM with #EM.  Other constructs have straightforward
  120.    translations, as illustrated by the following examples.  Note
  121.    that examples involving macro parameters have double pound
  122.    signs, since the condition will be tested when the macro is
  123.    expanded, not when it is defined.
  124.  
  125.    MASM construct              Equivalent A86 construct
  126.  
  127.    IFE expr                     #IF ! expr
  128.    IFB <PARM3>                  ##IF !#S3
  129.    IFNB <PARM4>                 ##IF #S4
  130.    IFIDN <PARM1>,<CX>           ##IF "#1" EQ "CX"
  131.    IFDIF <PARM2>,<SI>           ##IF "#2" NE "SI"
  132.    .ERR                         (any undefined symbol)
  133.    .ERRcond                     TRUE EQU 0FFFF
  134.                                 TRUE EQU cond
  135.    EXITM                        #EX
  136.    IRP ... ENDM                 #RX1L ... #ER
  137.    REPT 100 ...ENDM             #RX1(100) ... #ER
  138.    IRPC ... ENDM                #CX ... #EC
  139.  
  140.    The last three constructs, IRP, REPT, and IRPC, usually occur
  141.    within macros; but in MASM they don't have to.  The A86
  142.    equivalents are valid only within macros-- if they occur in
  143.    the MASM program outside of a macro, you duplicate them by
  144.    defining an enclosing macro on the spot, and calling that
  145.    macro once, right after it is defined.
  146.  
  147.    To retain compatibility, you isolate the old macro definitions
  148.    in an INCLUDE file (A86 will ignore the INCLUDE directive),
  149.    and isolate the A86 macro definitions in a separate file, not
  150.    used in an MASM assembly of the program.
  151.  
  152. 5. A86 supports the STRUC directive, with named structure
  153.    elements, just like MASM, with one exception: A86 does not
  154.    save initial values declared in the STRUC definition, and A86
  155.    does not allow assembly of instances of structure elements.
  156.  
  157.    For example, the MASM construct
  158.  
  159.    PAYREC STRUC
  160.       PNAME  DB 'no name given'
  161.       PKEY   DW ?
  162.    ENDS
  163.  
  164.    PAYREC 3 DUP (?)
  165.    PAYREC <'Eric',1811>
  166.                                                              12-4
  167.  
  168.    causes A86 to accept the STRUC definition, and define the
  169.    structure elements PNAME and PKEY correctly; but the PAYREC
  170.    initializations need to be recoded.  If it isn't vital to
  171.    initialize the memory with the specific definition values, you
  172.    could recode the first PAYREC as:
  173.  
  174.    DB  ((TYPE PAYREC) * 3) DUP ?
  175.  
  176.    If you must initialize values, you do so line by line:
  177.  
  178.    DB 'Eric         '
  179.    DW ?
  180.  
  181.    If there are many such initializations, you could define a
  182.    macro INIT_PAYREC containing the DB and DW lines.
  183.  
  184. 6. A86 does not support a couple of the more exotic features of
  185.    MASM assembly language: the RECORD directive and its
  186.    associated operators WIDTH and MASK; and the usage of angle-
  187.    brackets to initialize structure records.  These features
  188.    would have added much complication to the internal structure
  189.    of symbol tables in A86; degrading the speed and the
  190.    reliability of the assembler.  I felt that their use was
  191.    sufficiently rare that it was not worth including them for
  192.    compatibility.  I would like to hear some feedback on this.
  193.    Does anybody out there use these features heavily?  Will they
  194.    be missed in A86?
  195.  
  196.    If your old program does use these features, you will have to
  197.    re-work the areas that use them.  Macros can be used to
  198.    duplicate the record and structure initializations.  Explicit
  199.    symbol declarations can replace the usage of the WIDTH and
  200.    MASK operators.
  201.  
  202.  
  203. Compatibility symbols recognized by A86
  204.  
  205. A86 has been programmed to ignore a variety of lines that have
  206. meaning to Intel/IBM/MASM assemblers; but which do nothing for
  207. A86.  These include lines beginning with a period (except .RADIX,
  208. which is acted upon), percent sign, or dollar sign; and lines
  209. beginning with ASSUME, INCLUDE, PAGE, SUBTTL, and TITLE. If you
  210. are porting your program to A86, and you wish to retain the
  211. option of returning to the other assembler, you may leave those
  212. lines in your program.  If you decide to stay with A86, you can
  213. remove those lines at your leisure.
  214.  
  215. In addition, there is a class of symbols now recognized by A86 in
  216. its .OBJ mode, but still ignored in .COM mode.  This includes
  217. NAME, END, and PUBLIC.
  218.  
  219. Named SEGMENT and ENDS directives written for other assemblers
  220. are, of course, recognized by A86's .OBJ mode.  In non-OBJ mode,
  221. A86 treats these as CODE SEGMENT directives.  A special exception
  222. to this is the directive
  223.  
  224.     segname SEGMENT AT atvalue
  225.                                                              12-5
  226.  
  227. which is treated by A86 as if it were the following sequence:
  228.  
  229.     segname EQU atvalue
  230.     STRUC
  231.  
  232. This will accomplish what is usually intended when SEGMENT AT is
  233. used in a program intended to be a COM file.
  234.  
  235.  
  236.  
  237. Conversion of A86 Programs to Intel/IBM/MASM
  238.  
  239. I consider this section a bit of a blasphemy, since it's a little
  240. silly to port programs from a superior assembler, to run on an
  241. inferior one.  However, I myself have been motivated to do so
  242. upon occasion, when programming for a client not familiar with
  243. A86; or whose computer doesn't run A86; who therefore wants the
  244. final version to assemble on Intel's assembler.  Since my
  245. assembler/debugger environment is so vastly superior to any other
  246. environment, I develop the program using my assembler, and port
  247. it to the client's environment at the end.
  248.  
  249. The main key to success in following the above scenarios is to
  250. exercise supreme will power, and not use any of the wonderful
  251. language features that exist on A86, but not on MASM. This is
  252. often not easy; and I have devised some methods for porting my
  253. features to other assemblers:
  254.  
  255. 1. I hate giving long sequences of PUSHes and POPs on separate
  256.    lines.  If the program is to be ported to a lesser assembler,
  257.    then I put the following lines into a file that only A86 will
  258.    see:
  259.  
  260.       PUSH2 EQU PUSH
  261.       PUSH3 EQU PUSH
  262.       POP2 EQU POP
  263.       POP3 EQU POP
  264.  
  265.    I define macros PUSH2, PUSH3, POP2, POP3 for the lesser
  266.    assembler, that PUSH or POP the appropriate number of
  267.    operands.  Then, everywhere in the program where I would
  268.    ordinarily use A86's multiple PUSH/POP feature, I use one or
  269.    more of the PUSHn/POPn mnemonics instead.
  270.  
  271. 2. I refrain from using the feature of A86 whereby constants with
  272.    a leading zero are default-hexadecimal.  All my hex constants
  273.    end with H.
  274.  
  275. 3. I will usually go ahead and use my local labels L0 through L9;
  276.    then at the last minute convert them to a long set of labels
  277.    in sequence: Z100, Z101, Z102, etc.  I take care to remove all
  278.    the ">" forward reference specifiers when I make the
  279.    conversion.  The "Z" is used to isolate the local labels at
  280.    the end of the lesser assembler's symbol table listing. This
  281.    improves the quality of the final program so much that it is
  282.    worth the extra effort needed to convert L0--L9's to Z100--
  283.    Zxxx's.
  284.                                                              12-6
  285.  
  286. 4. I will place declarations B EQU DS:BYTE PTR 0 and W EQU
  287.    DS:WORD PTR 0 at the top of the program.  Recall that A86 has
  288.    a "duplicate definition" feature whereby you can EQU an
  289.    already-existing symbol, as long as it is equated to the value
  290.    it already has.  This feature extends to the built in symbols
  291.    B and W, so A86 will look at those equates and essentially
  292.    ignore them.  On the old assembler, the effect of the
  293.    declarations is to add A86's notation to the old language.
  294.    Example:
  295.  
  296.      B EQU DS:BYTE PTR 0
  297.      W EQU DS:WORD PTR 0
  298.      MOV AX,W[0100]       ; replaces MOV AX, DS:WORD PTR 0100
  299.      MOV AL,B[BX]         ; replaces MOV AL, DS:BYTE PTR [BX]
  300.  
  301.